'use client';

import { PAGE_NUM } from '@/lib/constants';
import type { transError } from '@/service/error';
import type { Pagination } from '@/service/type/pagination';
import {
  type ColumnDef,
  type Table as ReactTable,
  flexRender,
  getCoreRowModel,
  useReactTable,
} from '@tanstack/react-table';
import { usePathname, useRouter, useSearchParams } from 'next/navigation';
import { use, useImperativeHandle, useState } from 'react';
import { Button } from './button';
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from './table';

type DataRes<T> =
  | {
      result: Pagination<T>;
      error: null;
    }
  | {
      result: null;
      error: ReturnType<typeof transError>;
    };

type DataTableProps<TData> = {
  pageData: Promise<DataRes<TData>>;
  columns: ColumnDef<TData>[];
  ref?: React.RefObject<ReactTable<TData> | null>;
};

export default function DataTable<TData>({
  pageData,
  columns,
  ref,
}: DataTableProps<TData>) {
  const data = use(pageData);
  if (data.error) throw new Error(data.error.message);

  const searchParams = useSearchParams();
  const pathname = usePathname();
  const { replace } = useRouter();
  const [rowSelection, setRowSelection] = useState({});
  const page = searchParams.get('page')
    ? Number(searchParams.get('page'))
    : PAGE_NUM;

  const table = useReactTable({
    data: data.result.data,
    columns,
    getCoreRowModel: getCoreRowModel(),
    manualPagination: true,
    onRowSelectionChange: setRowSelection,
    state: {
      rowSelection,
    },
  });

  const handlePageChange = (newPage: number) => {
    const search = new URLSearchParams(searchParams);
    search.set('page', String(newPage));
    replace(`${pathname}?${search.toString()}`);
    table.resetRowSelection();
  };

  useImperativeHandle(ref, () => table, [table]);

  return (
    <div className="w-full">
      <div className="rounded-md border">
        <Table>
          <TableHeader>
            {table.getHeaderGroups().map((headerGroup) => (
              <TableRow key={headerGroup.id}>
                {headerGroup.headers.map((header) => {
                  return (
                    <TableHead key={header.id}>
                      {header.isPlaceholder
                        ? null
                        : flexRender(
                            header.column.columnDef.header,
                            header.getContext(),
                          )}
                    </TableHead>
                  );
                })}
              </TableRow>
            ))}
          </TableHeader>
          <TableBody>
            {table.getRowModel().rows?.length ? (
              table.getRowModel().rows.map((row) => (
                <TableRow
                  key={row.id}
                  data-state={row.getIsSelected() && 'selected'}
                >
                  {row.getVisibleCells().map((cell) => (
                    <TableCell key={cell.id}>
                      {flexRender(
                        cell.column.columnDef.cell,
                        cell.getContext(),
                      )}
                    </TableCell>
                  ))}
                </TableRow>
              ))
            ) : (
              <TableRow>
                <TableCell
                  colSpan={columns.length}
                  className="h-24 text-center"
                >
                  无数据
                </TableCell>
              </TableRow>
            )}
          </TableBody>
        </Table>
      </div>
      <div className="flex items-center justify-end space-x-2 py-4">
        <Button
          variant="outline"
          size="sm"
          onClick={() => handlePageChange(page - 1)}
          disabled={page <= 1}
        >
          上一页
        </Button>
        <Button
          variant="outline"
          size="sm"
          onClick={() => handlePageChange(page + 1)}
          disabled={!data.result.next}
        >
          下一页
        </Button>
      </div>
    </div>
  );
}
